package builder

import (
	"context"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"goproject/commonType"
	"goproject/logger"
	"goproject/mongodb/testCase"
	"goproject/mongodb/testMicroservice"
	"strconv"
)

// 生成测试微服务
func GenerateAndStoreTestMicroservice(traceTree commonType.TraceTree, faultConfigs []commonType.FaultConfig, recordID primitive.ObjectID, testMicroserviceStore *testMicroservice.Store) ([]commonType.TestMicroservice, error) {
	log := logger.GetLogger()
	// 声明一个testMicroservice切片
	log.Infof("生成测试微服务")
	var testMicroservicesList []commonType.TestMicroservice
	for _, faultConfig := range faultConfigs {
		var traceRequests []commonType.Request

		for _, node := range traceTree.Nodes {
			if node.ServiceName == faultConfig.ServiceName {
				traceRequests = node.TraceRequest
				break
			}
		}

		testMicroservice := commonType.TestMicroservice{
			RecordID:     &recordID,
			Name:         faultConfig.ServiceName,
			TestStatus:   0,
			FaultList:    faultConfig.FaultList,
			TraceRequest: traceRequests,
		}
		testMicroservice, err := testMicroserviceStore.Create(context.Background(), testMicroservice)
		if err != nil {
			log.Errorf("创建测试微服务 %s 失败: %s", faultConfig.ServiceName, err)
			return []commonType.TestMicroservice{}, err
		}
		testMicroservicesList = append(testMicroservicesList, testMicroservice)
		log.Infof("测试微服务 %s 创建并存储成功", faultConfig.ServiceName)
	}

	return testMicroservicesList, nil
}

// 获取下游微服务
func GetDownstreamMicroservices(c *context.Context, task commonType.Task, testMicroservice commonType.TestMicroservice, testMicroserviceStore *testMicroservice.Store) ([]commonType.TestMicroservice, error) {
	log := logger.GetLogger()
	var downstreamMicroservices []commonType.TestMicroservice

	// Find the source node based on the service name
	var sourceNodeID int
	for _, node := range task.TraceTree.Nodes {
		if node.ServiceName == testMicroservice.Name {
			sourceNodeID = node.ID
			break
		}
	}

	// Find all edges with the source node ID
	var targetEdgeList []commonType.Edge
	for _, edge := range task.TraceTree.Edges {
		if edge.Source == sourceNodeID {
			targetEdgeList = append(targetEdgeList, edge)
		}
	}

	// Find the downstream microservices based on the target edges
	for _, edge := range targetEdgeList {
		for _, node := range task.TraceTree.Nodes {
			if node.ID == edge.Target {
				// Find the corresponding downstream microservice in the database
				microservices, err := testMicroserviceStore.GetByNameAndRecordId(context.Background(), node.ServiceName, *testMicroservice.RecordID)
				if err != nil {
					log.Errorf("获取下游微服务 %s 失败: %s", node.ServiceName, err)
					return nil, err
				}
				downstreamMicroservices = append(downstreamMicroservices, microservices)
			}
		}
	}

	log.Infof("下游微服务获取成功: %v", downstreamMicroservices)
	return downstreamMicroservices, nil
}

// 生成下游响应依赖组合
func getResponseCombine(c *context.Context, downstreamMicroservices []commonType.TestMicroservice, testCaseStore *testCase.Store) ([][]commonType.TestCase, error) {
	log := logger.GetLogger()
	log.Infof("下游响应依赖微服务：%s 个", strconv.Itoa(len(downstreamMicroservices)))
	ctx := context.Background()
	var allTestCases [][]commonType.TestCase

	for _, microservice := range downstreamMicroservices {
		testCases, err := testCaseStore.GetListByTestMicroserviceId(context.Background(), *microservice.ID, 0, 0)
		log.Debugf("下游微服务 %s 测试用例：%d 个", microservice.Name, strconv.Itoa(len(testCases)))
		if err != nil {
			log.Errorf("获取下游微服务的测试用例失败: %s", err)
			return nil, err
		}
		allTestCases = append(allTestCases, testCases)
	}
	log.Debugf("全部测试用例长度：%s", strconv.Itoa(len(allTestCases)))
	for i, tcs := range allTestCases {
		log.Debugf("第%s组测试用例长度：%s", i, strconv.Itoa(len(tcs)))
	}
	combinedTestCases := combineTestCases(&ctx, allTestCases)
	log.Infof("最终组合结果长度: %v", len(combinedTestCases))
	return combinedTestCases, nil
}

func combineTestCases(c *context.Context, lists [][]commonType.TestCase) [][]commonType.TestCase {
	log := logger.GetLogger()
	if len(lists) == 0 {
		log.Infof("输入列表为空，返回 nil")
		return nil
	}
	if len(lists) == 1 {
		var result [][]commonType.TestCase
		for _, item := range lists[0] {
			result = append(result, []commonType.TestCase{item})
		}
		log.Infof("输入列表长度为 1，返回结果: %v", result)
		return result
	}

	var result [][]commonType.TestCase
	for _, item := range lists[0] {
		log.Infof("处理 item: %v", item)
		for _, subResult := range combineTestCases(c, lists[1:]) {
			combined := append([]commonType.TestCase{item}, subResult...)
			result = append(result, combined)
		}
	}
	return result
}

// 生成测试用例
func GenerateTestCases(c *context.Context, testCaseStore *testCase.Store, currentTestMicroservice commonType.TestMicroservice, downstreamMicroservices []commonType.TestMicroservice) ([]commonType.TestCase, error) {
	// 声明测试用例切片
	testCaseList := []commonType.TestCase{}
	log := logger.GetLogger()
	ctx := context.TODO()
	log.Infof("测试微服务ID：%s", currentTestMicroservice)
	// 获取下游测试微服务的测试用例组合
	combinedTestCases, err := getResponseCombine(c, downstreamMicroservices, testCaseStore)
	if err != nil {
		log.Errorf("生成测试用例组合失败: %s", err)
		return []commonType.TestCase{}, err
	}

	// 遍历当前微服务的故障列表，生成测试用例 还需要处理无故障的情况
	for _, fault := range currentTestMicroservice.FaultList {
		for _, request := range currentTestMicroservice.TraceRequest {
			if len(combinedTestCases) == 0 {
				testCase := commonType.TestCase{
					TestMicroserviceID: currentTestMicroservice.ID,
					SelectedFault:      fault,
					SelectedReq:        request,
					Dependency:         []commonType.TestCase{},
					Status:             0,
					Response:           commonType.StoredResponse{},
				}
				testCase, err := testCaseStore.Create(ctx, testCase)
				if err != nil {
					log.Errorf("创建测试用例失败: %s", err)
					return []commonType.TestCase{}, err
				}
				testCaseList = append(testCaseList, testCase)

				testCase_nofault := commonType.TestCase{
					TestMicroserviceID: currentTestMicroservice.ID,
					SelectedFault:      commonType.Fault{},
					SelectedReq:        request,
					Dependency:         []commonType.TestCase{},
					Status:             0,
					Response:           commonType.StoredResponse{},
				}
				testCase_nofault, err = testCaseStore.Create(ctx, testCase_nofault)
				if err != nil {
					log.Errorf("创建测试用例失败: %s", err)
					return []commonType.TestCase{}, err
				}
				testCaseList = append(testCaseList, testCase_nofault)

			} else {
				for _, combined := range combinedTestCases {
					var dependencies []commonType.TestCase
					dependencies = combined
					testCase := commonType.TestCase{
						TestMicroserviceID: currentTestMicroservice.ID,
						SelectedFault:      fault,
						SelectedReq:        request,
						Dependency:         dependencies,
						Status:             0,
						Response:           commonType.StoredResponse{},
					}
					testCase, err := testCaseStore.Create(ctx, testCase)
					if err != nil {
						log.Errorf("创建测试用例失败: %s", err)
						return []commonType.TestCase{}, err
					}
					testCaseList = append(testCaseList, testCase)
					testCase_nofault := commonType.TestCase{
						TestMicroserviceID: currentTestMicroservice.ID,
						SelectedFault:      commonType.Fault{},
						SelectedReq:        request,
						Dependency:         []commonType.TestCase{},
						Status:             0,
						Response:           commonType.StoredResponse{},
					}
					testCase_nofault, err = testCaseStore.Create(ctx, testCase_nofault)
					if err != nil {
						log.Errorf("创建测试用例失败: %s", err)
						return []commonType.TestCase{}, err
					}
					testCaseList = append(testCaseList, testCase_nofault)
				}
			}

		}
	}

	log.Infof("测试用例生成成功")
	return testCaseList, nil
}
